package com.bonc.modules.rpt.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bonc.common.utils.ObjectUtil;
import com.bonc.datasource.annotation.DataSource;
import com.bonc.modules.rpt.dao.ComplainSatisfationAreaDao;
import com.bonc.modules.rpt.dao.ComplainSatisfationRegionDao;
import com.bonc.modules.rpt.entity.ComplainSatisfactionAreaEntity;
import com.bonc.modules.rpt.entity.ComplainSatisfactionRegionEntity;
import com.bonc.modules.rpt.param.SurveyParam;
import com.bonc.modules.rpt.result.SurveyResult;
import com.bonc.modules.rpt.result.SurveyResultY;
import com.bonc.modules.rpt.service.ComplainSatisfationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@DataSource("data")
@Service("complainSatisfationService")
public class ComplainSatisfationServiceImpl implements ComplainSatisfationService {

    @Autowired
    private ComplainSatisfationRegionDao complainSatisfationRegionDao;

    @Autowired
    private ComplainSatisfationAreaDao complainSatisfationAreaDao;

    private List<Integer> getRecentMonth(Integer endDate, int num){
        LocalDateTime localDateTime = LocalDateTime.of(endDate.intValue() / 100, endDate.intValue() % 100, 1, 0, 0);
        List<Integer> dateList = new ArrayList<Integer>();
        for(int i = 0; i < num; i++){
            dateList.add(localDateTime.getYear() * 100 + localDateTime.getMonthValue());
            localDateTime = localDateTime.minus( 1, ChronoUnit.MONTHS);
        }
        return dateList;
    }

    private void generateSituationByCityXAxis(SurveyResult surveyResult, List<ComplainSatisfactionAreaEntity> complainSatisfactionCityEntityList){
        for (ComplainSatisfactionAreaEntity complainSatisfactionCityEntity : complainSatisfactionCityEntityList) {
            surveyResult.getXAxis().add(complainSatisfactionCityEntity.getCityDesc() == null ? "" : complainSatisfactionCityEntity.getCityDesc().trim());
        }
    }

    private void generateSituationByCityValueResult(SurveyResult surveyResult, List<ComplainSatisfactionAreaEntity> complainSatisfactionCityEntityList){
        SurveyResultY surveyResultY = new SurveyResultY();
        surveyResultY.setLegend("");
        for (ComplainSatisfactionAreaEntity complainSatisfactionCityEntity : complainSatisfactionCityEntityList) {
            surveyResultY.getData().add(complainSatisfactionCityEntity.getSatisfationRate().toString());
        }
        surveyResult.getYAxis().add(surveyResultY);
    }

    private void generateSituationByRegionXAxis(SurveyResult surveyResult, List<ComplainSatisfactionRegionEntity> complainSatisfactionRegionEntityList){
        for (ComplainSatisfactionRegionEntity complainSatisfactionRegionEntity : complainSatisfactionRegionEntityList) {
            surveyResult.getXAxis().add(complainSatisfactionRegionEntity.getRegionDesc() == null ? "" : complainSatisfactionRegionEntity.getRegionDesc().trim());
        }
    }

    private void generateSituationByRegionValueResult(SurveyResult surveyResult, List<ComplainSatisfactionRegionEntity> complainSatisfactionRegionEntityList){
        SurveyResultY surveyResultY = new SurveyResultY();
        surveyResultY.setLegend("");
        for (ComplainSatisfactionRegionEntity complainSatisfactionRegionEntity : complainSatisfactionRegionEntityList) {
            surveyResultY.getData().add(complainSatisfactionRegionEntity.getSatisfationRate().toString());
        }
        surveyResult.getYAxis().add(surveyResultY);
    }

    private SurveyResult selectSituationByRegion(SurveyParam surveyParam){
        LambdaQueryWrapper<ComplainSatisfactionRegionEntity> queryWrapper = new LambdaQueryWrapper<>();
        if(!ObjectUtil.isEmptyObject(surveyParam.getIfGuarantee())){
            queryWrapper.eq(ComplainSatisfactionRegionEntity::getIfGuarantee, surveyParam.getIfGuarantee());
        }
        if(!ObjectUtil.isEmptyObject(surveyParam.getDealDate())){
            queryWrapper.eq(ComplainSatisfactionRegionEntity::getDealDate, surveyParam.getDealDate());
        }
        queryWrapper.ne(ComplainSatisfactionRegionEntity::getRegionCode, surveyParam.getRegionCode());
        queryWrapper.orderByAsc(ComplainSatisfactionRegionEntity::getRegionCode);

        List<ComplainSatisfactionRegionEntity> complainSatisfactionRegionEntityList = complainSatisfationRegionDao.selectList(queryWrapper);
        SurveyResult surveyResult = new SurveyResult();
        if(!ObjectUtil.isEmptyObject(complainSatisfactionRegionEntityList)){
            generateSituationByRegionXAxis(surveyResult, complainSatisfactionRegionEntityList);
            generateSituationByRegionValueResult(surveyResult, complainSatisfactionRegionEntityList);
        }

        return surveyResult;
    }

    private SurveyResult selectSituationByCity(SurveyParam surveyParam){
        LambdaQueryWrapper<ComplainSatisfactionAreaEntity> queryWrapper = new LambdaQueryWrapper<>();
        if(!ObjectUtil.isEmptyObject(surveyParam.getIfGuarantee())){
            queryWrapper.eq(ComplainSatisfactionAreaEntity::getIfGuarantee, surveyParam.getIfGuarantee());
        }
        if(!ObjectUtil.isEmptyObject(surveyParam.getDealDate())){
            queryWrapper.eq(ComplainSatisfactionAreaEntity::getDealDate, surveyParam.getDealDate());
        }
        if(!ObjectUtil.isEmptyObject(surveyParam.getRegionCode())){
            queryWrapper.eq(ComplainSatisfactionAreaEntity::getRegionCode, surveyParam.getRegionCode());
        }
        queryWrapper.orderByAsc(ComplainSatisfactionAreaEntity::getCityCode);

        List<ComplainSatisfactionAreaEntity> complainSatisfactionCityEntityList = complainSatisfationAreaDao.selectList(queryWrapper);
        SurveyResult surveyResult = new SurveyResult();
        if(!ObjectUtil.isEmptyObject(complainSatisfactionCityEntityList)){
            generateSituationByCityXAxis(surveyResult, complainSatisfactionCityEntityList);
            generateSituationByCityValueResult(surveyResult, complainSatisfactionCityEntityList);
        }

        return surveyResult;
    }


    private Map<Integer, BigDecimal> selectComplainSatisfactionRegionEntityList(SurveyParam surveyParam, List<Integer> dateList){
        LambdaQueryWrapper<ComplainSatisfactionRegionEntity> queryWrapper = new LambdaQueryWrapper<>();
        if(!ObjectUtil.isEmptyObject(surveyParam.getDealDate())){
            queryWrapper.in(ComplainSatisfactionRegionEntity::getDealDate, dateList);
        }
        if(!ObjectUtil.isEmptyObject(surveyParam.getRegionCode())){
            queryWrapper.eq(ComplainSatisfactionRegionEntity::getRegionCode, surveyParam.getRegionCode());
        }
        if(!ObjectUtil.isEmptyObject(surveyParam.getIfGuarantee())){
            queryWrapper.eq(ComplainSatisfactionRegionEntity::getIfGuarantee, surveyParam.getIfGuarantee());
        }
        queryWrapper.orderByDesc(ComplainSatisfactionRegionEntity::getIfGuarantee, ComplainSatisfactionRegionEntity::getDealDate);
        List<ComplainSatisfactionRegionEntity> complainSatisfactionRegionEntityList = complainSatisfationRegionDao.selectList(queryWrapper);
        return complainSatisfactionRegionEntityList.stream().collect(Collectors.toMap(complainSatisfactionRegionEntity-> complainSatisfactionRegionEntity.getDealDate(), ComplainSatisfactionRegionEntity::getSatisfationRate));
    }

    @Override
    public SurveyResult<Map<String, Object>> getComplainSatisfation(SurveyParam surveyParam) {
        Map<String, Object> map = new HashMap<String, Object>();
        List<Integer> dateList = getRecentMonth(surveyParam.getDealDate(), 2);

        surveyParam.setIfGuarantee("1");
        Map<Integer, BigDecimal> resultGuarantee = selectComplainSatisfactionRegionEntityList(surveyParam, dateList);
        map.put("guarantee", resultGuarantee.get(surveyParam.getDealDate()) == null ? "--" : resultGuarantee.get(surveyParam.getDealDate()));
        if(resultGuarantee.get(dateList.get(0)) != null && resultGuarantee.get(dateList.get(1)) != null){
            map.put("guaranteeRatio", resultGuarantee.get(dateList.get(0)).subtract(resultGuarantee.get(dateList.get(1))));
        } else {
            map.put("guaranteeRatio", "--");
        }

        surveyParam.setIfGuarantee("0");
        Map<Integer, BigDecimal> resultCommon = selectComplainSatisfactionRegionEntityList(surveyParam, dateList);
        map.put("common", resultCommon.get(surveyParam.getDealDate()) == null ? "--" : resultCommon.get(surveyParam.getDealDate()));
        if(resultCommon.get(dateList.get(0)) != null && resultCommon.get(dateList.get(1)) != null){
            map.put("commonRatio", resultCommon.get(dateList.get(0)).subtract(resultCommon.get(dateList.get(1))));
        } else {
            map.put("commonRatio", "--");
        }

        SurveyResult<Map<String, Object>> surveyResult = new SurveyResult<Map<String, Object>>();
        surveyResult.setData(map);

        return surveyResult;
    }

    @Override
    public SurveyResult getTrend(SurveyParam surveyParam) {
        List<Integer> dateList = getRecentMonth(surveyParam.getDealDate(), 13);
        surveyParam.setIfGuarantee("1");
        Map<Integer, BigDecimal> resultGuarantee = selectComplainSatisfactionRegionEntityList(surveyParam, dateList);
        surveyParam.setIfGuarantee("0");
        Map<Integer, BigDecimal> resultCommon = selectComplainSatisfactionRegionEntityList(surveyParam, dateList);
        SurveyResult surveyResult = new SurveyResult();
        SurveyResultY surveyResultYCommon = new SurveyResultY();
        surveyResultYCommon.setLegend("普通投诉");
        SurveyResultY surveyResultYGuarantee = new SurveyResultY();
        surveyResultYGuarantee.setLegend("报障");
        SurveyResultY surveyResultYCommonRate = new SurveyResultY();
        surveyResultYCommonRate.setLegend("普通投诉环比");
        SurveyResultY surveyResultYGuaranteeRate = new SurveyResultY();
        surveyResultYGuaranteeRate.setLegend("报障环比");

        BigDecimal lastValueCommon = resultCommon.get(dateList.get(12)) == null ? new BigDecimal(0) : resultCommon.get(dateList.get(12));
        BigDecimal lastValueGuarantee = resultGuarantee.get(dateList.get(12)) == null ? new BigDecimal(0) : resultGuarantee.get(dateList.get(12));
        for(int i = 11; i >= 0; i--){
            Integer year = dateList.get(i) / 100;
            int month = dateList.get(i) % 100;
            String xAxis = year + "年" + (month < 10 ? "0" + month : month) + "月";
            surveyResult.getXAxis().add(xAxis);
            BigDecimal curValueCommon = resultCommon.get(dateList.get(i)) == null ? new BigDecimal(0) : resultCommon.get(dateList.get(i));
            BigDecimal curValueGuarantee = resultGuarantee.get(dateList.get(i)) == null ? new BigDecimal(0) : resultGuarantee.get(dateList.get(i));
            surveyResultYCommon.getData().add(curValueCommon.toString());
            surveyResultYGuarantee.getData().add(curValueGuarantee.toString());
            surveyResultYCommonRate.getData().add(curValueCommon.subtract(lastValueCommon).toString());
            surveyResultYGuaranteeRate.getData().add(curValueGuarantee.subtract(lastValueGuarantee).toString());

            lastValueCommon = curValueCommon;
            lastValueGuarantee = curValueGuarantee;
        }
        surveyResult.getYAxis().add(surveyResultYCommon);
        surveyResult.getYAxis().add(surveyResultYGuarantee);
        surveyResult.getYAxis().add(surveyResultYCommonRate);
        surveyResult.getYAxis().add(surveyResultYGuaranteeRate);

        return surveyResult;
    }

    @Override
    public SurveyResult getSituationCommon(SurveyParam surveyParam) {

        SurveyResult surveyResult = null;
        surveyParam.setIfGuarantee("0");
        if(!ObjectUtil.isEmptyObject(surveyParam)
                && "00".equals(surveyParam.getRegionCode())){
            surveyResult = this.selectSituationByRegion(surveyParam);
        }
        if(!ObjectUtil.isEmptyObject(surveyParam)
                && !"00".equals(surveyParam.getRegionCode())){
            surveyResult = this.selectSituationByCity(surveyParam);
        }

        return surveyResult;
    }

    @Override
    public SurveyResult getSituationGuarantee(SurveyParam surveyParam){

        SurveyResult surveyResult = null;
        surveyParam.setIfGuarantee("1");
        if(!ObjectUtil.isEmptyObject(surveyParam)
                && "00".equals(surveyParam.getRegionCode())){
            surveyResult = this.selectSituationByRegion(surveyParam);
        }
        if(!ObjectUtil.isEmptyObject(surveyParam)
                && !"00".equals(surveyParam.getRegionCode())){
            surveyResult = this.selectSituationByCity(surveyParam);
        }

        return surveyResult;
    }
}
